package com.iocup.keybastion.core.impl;


import com.iocup.keybastion.context.SecurityContext;
import com.iocup.keybastion.core.HttpActionAdapter;
import com.iocup.keybastion.context.SecurityContextHolder;
import com.iocup.keybastion.context.WebContextHolder;
import com.iocup.keybastion.core.SecurityGrantedAccessAdapter;
import com.iocup.keybastion.core.SecurityLogicChecker;
import com.iocup.keybastion.core.matching.MatchingChecker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * @author xyjxust
 * @create 2022/3/21 11:35
 **/
@Slf4j
public class DefaultSecurityLogicChecker implements SecurityLogicChecker {

    /**
     * 匹配检查器
     */
    private MatchingChecker matchingChecker;


    /**
     * 登录之前的一些逻辑
     */
    private List<SecurityLogicChecker> securityLogicCheckers = new ArrayList<>();


    public DefaultSecurityLogicChecker(MatchingChecker matchingChecker) {
        this.matchingChecker = matchingChecker;

    }


    /**
     * 添加前置检查器
     *
     * @param securityLogicChecker
     * @return
     */
    public DefaultSecurityLogicChecker addChecker(SecurityLogicChecker... securityLogicChecker) {
        securityLogicCheckers.addAll(Arrays.asList(securityLogicChecker));
        return this;
    }


    @Override
    public Object handle(WebContextHolder contextHolder, SecurityGrantedAccessAdapter accessAdapter, HttpActionAdapter actionAdapter) {
        try {
            //设置安全认证上下文
            SecurityContextHolder.setContext(new SecurityContext(contextHolder));
            //进入安全匹配器
            boolean matchResult = matchingChecker.matches(contextHolder);
            //未通过就进行报错
            if (!matchResult) {
                throw new SecurityException("未通过安全匹配器");
            }
            //如果匹配通过了,就进入下一步
            log.debug("请求通过匹配器：url->{}", contextHolder.getRequestURL());
            if (CollectionUtils.isEmpty(securityLogicCheckers)) {
                return accessAdapter.adapt(contextHolder);
            }
            Iterator<SecurityLogicChecker> iterator = securityLogicCheckers.iterator();
            SecurityLogicChecker securityLogicChecker = iterator.next();
            SecurityGrantedAccessAdapter securityGrantedAccessAdapter = new SecurityGrantedAccessAdapter() {
                @Override
                public Object adapt(WebContextHolder webContextHolder) throws Exception {
                    if (iterator.hasNext()) {
                        iterator.next().handle(contextHolder, this, actionAdapter);
                    }
                    return null;
                }
            };
            securityLogicChecker.handle(contextHolder,
                    securityGrantedAccessAdapter, actionAdapter);
            return accessAdapter.adapt(contextHolder);
        } catch (Exception e) {
            return actionAdapter.adapt(e, contextHolder);
        } finally {
            //清除上下文
            SecurityContextHolder.clearContext();
        }
    }
}
